package cn.com.dingtek.genius.manager.server.web.controller;

import cn.com.dingtek.genius.manager.server.event.UserOperateEvent;
import cn.com.dingtek.genius.manager.server.repository.db.entity.AuthGroup;
import cn.com.dingtek.genius.manager.server.repository.db.entity.AuthGroupRule;
import cn.com.dingtek.genius.manager.server.service.AuthGroupService;
import cn.com.dingtek.genius.manager.server.support.sam.SecurityContextHolder;
import cn.com.dingtek.genius.manager.server.support.sam.annotation.AssertAuth;
import cn.com.dingtek.genius.manager.server.utils.IPUtil;
import cn.com.dingtek.genius.manager.server.web.Result;
import com.alibaba.fastjson.JSONObject;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

@RestController
@RequestMapping("/auth/group")
public class AuthGroupController {
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private AuthGroupService authGroupService;

    @AssertAuth
    @PostMapping("/list")
    public Result list(@RequestBody JSONObject json) {
        int currentPage = json.getInteger("current_page") == null ? 0 : json.getInteger("current_page");
        int pageSize = json.getInteger("page_size") == null ? 10 : json.getInteger("page_size");
        AuthGroup param = json.getObject("search_param", AuthGroup.class);
        return Result.ok(authGroupService.list(param, currentPage, pageSize));
    }

    @AssertAuth
    @PostMapping("/add")
    public Result add(@RequestBody JSONObject json, HttpServletRequest request) {
        long userId = SecurityContextHolder.getContext().getToken().getUserId();
        String account = SecurityContextHolder.getContext().getToken().getAccount();

        AuthGroup param = json.toJavaObject(AuthGroup.class);
        try {
            authGroupService.add(param, DateTime.now().toDate());
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("新增角色")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(true)
            );
        } catch (Exception e) {
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("新增角色")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(false)
            );
            throw e;
        }
        return Result.ok();
    }

    @AssertAuth
    @GetMapping("/info/{id}")
    public Result info(@PathVariable("id") Long id) {
        return Result.ok(authGroupService.info(id));
    }

    @AssertAuth
    @PostMapping("/update")
    public Result update(@RequestBody JSONObject json, HttpServletRequest request) {
        long userId = SecurityContextHolder.getContext().getToken().getUserId();
        String account = SecurityContextHolder.getContext().getToken().getAccount();

        AuthGroup param = json.toJavaObject(AuthGroup.class);
        try {
            authGroupService.update(param, DateTime.now().toDate());
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("修改角色")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(true)
            );
        } catch (Exception e) {
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("修改角色")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(false)
            );
            throw e;
        }
        return Result.ok();
    }

    @AssertAuth
    @GetMapping("/remove/{id}")
    public Result remove(@PathVariable("id") Long id, HttpServletRequest request) {
        long userId = SecurityContextHolder.getContext().getToken().getUserId();
        String account = SecurityContextHolder.getContext().getToken().getAccount();

        try {
            authGroupService.remove(id);
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("删除角色")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(true)
            );
        } catch (Exception e) {
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("删除角色")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(false)
            );
            throw e;
        }
        return Result.ok();
    }


    @AssertAuth
    @PostMapping("/grant")
    public Result grant(@RequestBody JSONObject json, HttpServletRequest request) {
        long userId = SecurityContextHolder.getContext().getToken().getUserId();
        String account = SecurityContextHolder.getContext().getToken().getAccount();

        AuthGroupRule param = json.toJavaObject(AuthGroupRule.class);
        try {
            authGroupService.grant(param, DateTime.now().toDate());
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("授权")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(true)
            );
        } catch (Exception e) {
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("授权")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(false)
            );
            throw e;
        }
        return Result.ok();
    }

    @AssertAuth
    @PostMapping("/ungrant")
    public Result unGrant(@RequestBody JSONObject json, HttpServletRequest request) {
        long userId = SecurityContextHolder.getContext().getToken().getUserId();
        String account = SecurityContextHolder.getContext().getToken().getAccount();

        AuthGroupRule param = json.toJavaObject(AuthGroupRule.class);
        try {
            authGroupService.unGrant(param, DateTime.now().toDate());
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("取消授权")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(true)
            );
        } catch (Exception e) {
            applicationEventPublisher.publishEvent(new UserOperateEvent(this)
                    .setUserId(userId)
                    .setAccountName(account)
                    .setOperateModule("角色管理")
                    .setOperateDesc("取消授权")
                    .setOperateIp(IPUtil.getIpAddress(request))
                    .setLogState(false)
            );
            throw e;
        }
        return Result.ok();
    }

    @AssertAuth
    @GetMapping("/options")
    public Result options() {
        return Result.ok(authGroupService.options());
    }
}
